package com.lsz.crm.service;

import com.lsz.crm.base.BaseService;
import com.lsz.crm.mapper.ModuleMapper;
import com.lsz.crm.mapper.PermissionMapper;
import com.lsz.crm.model.TreeModel;
import com.lsz.crm.pojo.Module;
import com.lsz.crm.utils.AssertUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author liushizhong
 * @Date 2021/10/30 15:26
 * @Version 1.0
 */

@Service
public class ModuleService extends BaseService<Module,Integer> {

    @Autowired
    private ModuleMapper moduleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 查询所有的资源,用于授权
     * @return
     */
    public List<TreeModel> queryAllModules(Integer roleId){
        // 查询所有的资源
        List<TreeModel> treeModels = moduleMapper.queryAllModules();
        // 查询指定角色授权过的资源列表
        List<Integer> permissionIds = permissionMapper.queryRoleHasModuleIdsByRoleId(roleId);
        // 判断角色是否拥有资源id
        if(permissionIds != null && permissionIds.size() > 0){
            // 循环资源列表，判断资源是否在用户授权的资源列表中，如果设置 checked 属性为 true
            treeModels.forEach(treeModel -> {
                if(permissionIds.contains(treeModel.getId())){
                    treeModel.setChecked(true);
                }
            });
        }
        return treeModels;
    }

    /**
     * 查询所有的资源，用于资源列表展示
     * @return
     */
    public Map<String,Object> queryModuleList(){
        Map<String,Object> map = new HashMap<>();
        // 查询资源列表
        List<Module> moduleList = moduleMapper.queryModules();
        map.put("code",0);
        map.put("msg","");
        map.put("count",moduleList.size());
        map.put("data",moduleList);
        return map;
    }

    /**
     * 添加资源
     *  1.参数校验
     * 模块名-module_name
     *       ⾮空 同⼀层级下模块名唯⼀
     * url
     *       ⼆级菜单 ⾮空 不可重复
     * 上级菜单-parent_id
     *      ⼀级菜单 -1
     *      ⼆级|三级菜单 parent_id ⾮空 必须存在
     * 层级-grade
     *      ⾮空 0|1|2
     * 权限码 optValue
     *     ⾮空 不可重复
     *  2.参数默认值设置
     *     is_valid create_date update_date
     *  3.执⾏添加 判断结果
     * @param module
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void addModule(Module module){
        // 1. 参数校验
        // 层级判断  0|1|2
        Integer grade = module.getGrade();
        AssertUtil.isTrue(grade == null || !(grade == 0 || grade == 1 || grade == 2),"菜单层级不合法！");
        // 模块名称校验 非空
        AssertUtil.isTrue(StringUtils.isBlank(module.getModuleName()),"菜单名称不能为空！");
        // 模块名称校验 同一层级下模块名称不能重复
        AssertUtil.isTrue(null != moduleMapper.queryModuleByGradeAndModuleName(grade,module.getModuleName()),"该层级下菜单名称已经存在！");

        // 如果是二级菜单 （grade = 1）
        if(grade == 1){
            // 地址 url 二级菜单非空
            AssertUtil.isTrue(StringUtils.isBlank(module.getUrl()),"二级菜单url不能为空！");
            // 地址 url 二级菜单不能重复
            AssertUtil.isTrue(null != moduleMapper.queryModuleByGradeAndUrl(grade,module.getUrl()),"⼆级菜单url不可重复!");
        }

        // 父级菜单
        if(grade == 0){
            module.setParentId(-1);
        }
        // ⼆级|三级菜单 parent_id ⾮空 必须存在
        if(grade != 0){
            Integer parentId = module.getParentId();
            AssertUtil.isTrue(null == parentId,"上级菜单不能为空！");
            AssertUtil.isTrue(null == moduleMapper.selectByPrimaryKey(parentId),"请指定正确的父级菜单！");
        }

        // 权限码 ⾮空 不可重复
        AssertUtil.isTrue(StringUtils.isBlank(module.getOptValue()),"权限码不能为空！");
        AssertUtil.isTrue(null != moduleMapper.queryModuleByOptValue(module.getOptValue()),"权限码重复!");

        // 2.设置默认值
        module.setIsValid((byte)1);
        module.setCreateDate(new Date());
        module.setUpdateDate(new Date());

        // 3.执⾏添加 判断结果
        AssertUtil.isTrue(moduleMapper.insertSelective(module) < 1,"菜单添加失败!");
    }

    /**
     * 更新资源
     *  1.参数校验
     *     id   ⾮空 记录存在
     *     层级-grade
     *         ⾮空 0|1|2
     *     模块名-module_name
     *         ⾮空 同⼀层级下模块名唯⼀
     *     url
     *         ⼆级菜单 ⾮空 不可重复
     *    上级菜单-parent_id
     *         ⼆级|三级菜单 parent_id ⾮空 必须存在
     *    权限码 optValue
     *        ⾮空 不可重复
     *  2.参数默认值设置
     *    update_date
     * 3.执⾏更新 判断结果
     * * @param module
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateModule(Module module) {
        // 1. 参数校验
        // id 校验
        AssertUtil.isTrue(null == module.getId() || null == moduleMapper.selectByPrimaryKey(module.getId()), "待更新记录不存在！");
        Integer grade = module.getGrade();
        // 层级校验
        AssertUtil.isTrue(null == grade || !(grade == 0 || grade == 1 || grade == 2), "菜单层级不合法！");
        // 模块名称校验
        AssertUtil.isTrue(StringUtils.isBlank(module.getModuleName()), "菜单名称不能为空！");
        Module temp = moduleMapper.queryModuleByGradeAndModuleName(grade, module.getModuleName());
        if (null != temp) {
            AssertUtil.isTrue(!(temp.getId().equals(module.getId())), "该层级下菜单已存在!");
        }
        // url 校验
        if (grade == 1) {
            AssertUtil.isTrue(StringUtils.isBlank(module.getUrl()), "二级菜单url不能为空！");
            temp = moduleMapper.queryModuleByGradeAndUrl(grade, module.getUrl());
            if (null != temp) {
                AssertUtil.isTrue(!(temp.getId().equals(module.getId())), "该层级下菜单url已存在！");
            }
        }
        // 上级菜单校验
        if (grade != 0) {
            Integer parentId = module.getParentId();
            AssertUtil.isTrue(null == parentId, "上级菜单不能为空!");
            AssertUtil.isTrue(null == moduleMapper.selectByPrimaryKey(parentId), "上级菜单不存在！");
        }
        // 权限码校验
        AssertUtil.isTrue(StringUtils.isBlank(module.getOptValue()), "权限码不能为空！");
        temp = moduleMapper.queryModuleByOptValue(module.getOptValue());
        if (null != temp) {
            AssertUtil.isTrue(!(temp.getId().equals(module.getId())), "权限码已存在!");
        }

        // 2. 设置默认参数
        module.setUpdateDate(new Date());

        // 3.执行添加操作
        AssertUtil.isTrue(moduleMapper.updateByPrimaryKeySelective(module) < 1,"菜单更新失败！");
    }

    /**
     * 删除资源
     * @param id
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteModule(Integer id){
        Module temp = moduleMapper.selectByPrimaryKey(id);
        AssertUtil.isTrue(null == id || null == temp ,"待删除记录不存在！");
        /*
          如果存在子菜单，不允许删除
         */
        int count = moduleMapper.countSubModuleByParentId(id);
        AssertUtil.isTrue(count > 0,"存在子菜单，不支持删除操作！");

        // 删除权限表里的相关资源
        count = permissionMapper.countPermissionByModuleId(id);
        if(count > 0){
            AssertUtil.isTrue(permissionMapper.deletePermissionsByModuleId(id) != count,"菜单删除失败！");
        }
        assert temp != null;
        temp.setIsValid((byte)0);
        temp.setUpdateDate(new Date());
        // 执行更新操作
        AssertUtil.isTrue(moduleMapper.updateByPrimaryKeySelective(temp) < 1,"菜单删除失败！");
    }
}
